package com.leonzhangxf.bucksdemo.order.infrastructure.repository.impl.po;

import com.google.common.base.Functions;
import com.leonzhangxf.bucksdemo.order.domain.Order;
import com.leonzhangxf.bucksdemo.order.domain.value.OrderAmount;
import com.leonzhangxf.bucksdemo.order.domain.value.OrderId;
import com.leonzhangxf.bucksdemo.order.domain.value.OrderStatusChangeLog;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class OrderAssembler {

    public void copyDo(Order order, OrderPO orderPO) {
        orderPO.setOrderId(order.getOrderId().getId());
        orderPO.setOrderAmount(order.getAmount().getAmount());
        orderPO.setOrderCurrency(order.getAmount().getCurrency());
        orderPO.setStatus(order.getStatus());

        Map<OrderStatusChangeLogPO, Long> statusChangeLogPOLongMap = orderPO.getStatusChangeLogs()
            .stream().collect(Collectors.toMap(Functions.identity(), OrderStatusChangeLogPO::getId));

        Set<OrderStatusChangeLogPO> logSet = order.getUnmodifiableStatusChangeLogs()
            .stream().map((log) -> {
                OrderStatusChangeLogPO logPO = new OrderStatusChangeLogPO();
                logPO.setBeforeStatus(log.getBeforeStatus());
                logPO.setAfterStatus(log.getAfterStatus());
                logPO.setChangeTime(log.getChangeTime());
                logPO.setOrder(orderPO);

                // 需要根据值对象匹配ID，防止新增已有数据
                Long logPoId = statusChangeLogPOLongMap.get(logPO);
                if (null != logPoId) {
                    logPO.setId(logPoId);
                }
                return logPO;
            }).collect(Collectors.toSet());
        orderPO.setStatusChangeLogs(logSet);
    }

    public OrderPO createPo(Order order) {
        OrderPO orderPO = new OrderPO();
        orderPO.setOrderId(order.getOrderId().getId());
        orderPO.setOrderAmount(order.getAmount().getAmount());
        orderPO.setOrderCurrency(order.getAmount().getCurrency());
        orderPO.setStatus(order.getStatus());

        Set<OrderStatusChangeLogPO> logSet = order.getUnmodifiableStatusChangeLogs()
            .stream().map((log) -> {
                OrderStatusChangeLogPO logPO = new OrderStatusChangeLogPO();
                logPO.setBeforeStatus(log.getBeforeStatus());
                logPO.setAfterStatus(log.getAfterStatus());
                logPO.setChangeTime(log.getChangeTime());
                logPO.setOrder(orderPO);
                return logPO;
            }).collect(Collectors.toSet());
        orderPO.setStatusChangeLogs(logSet);
        return orderPO;
    }

    public Order createDo(OrderPO orderPO) {
        if (null == orderPO) {
            return null;
        }
        OrderId orderId = new OrderId(orderPO.getOrderId());
        OrderAmount orderAmount = new OrderAmount(orderPO.getOrderAmount(), orderPO.getOrderCurrency());

        List<OrderStatusChangeLog> changeLogs = orderPO.getStatusChangeLogs().stream()
            .map(
                (logPO) -> new OrderStatusChangeLog(logPO.getBeforeStatus(),
                    logPO.getAfterStatus(), logPO.getChangeTime())
            ).collect(Collectors.toList());
        return new Order(orderId, orderAmount, orderPO.getStatus(), changeLogs);
    }
}
